% \iffalse meta-comment
%
%% File: latex2e-first-aid-for-external-files.dtx (C) Copyright 2020 
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%
% It may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%    https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This file has the LPPL maintenance status "maintained".
%
%
%
%<*driver>
\documentclass{ltxdoc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{latex2e-first-aid-for-external-files.dtx}
\end{document}
%</driver>
%
% \fi
%
%
% \providecommand\pkg[1]{\texttt{#1}}
%
% \title{First aid for external files and packages that need updating}
% \author{Frank Mittelbach, \LaTeX{} Project}
%
% \maketitle
%
%
% \begin{abstract}
%    This file contains some first aid for packages or classes that
%    require updates because of internal changes to \LaTeX{} but that
%    aren't yet reflected in the package/class code.
% \end{abstract}
%
% \tableofcontents
%
% \section{Introduction}
%
%    Over the years package writers have hooked into
%    various parts of internal \LaTeX{} commands (largely because
%    proper interfaces were missing in important places) and if
%    we are now gradually adding such interfaces these internal
%    commands do change and as a result patching into them stops
%    working.
%
%    As part of making such internal changes the \LaTeX{} Project team
%    attempts to check for such usage in packages, alert the package
%    maintainers and ensures that the packages get updated alongside
%    the core \LaTeX{} system. However it is not always possible to
%    get packages that will fail with a new kernel updated in time and
%    if that is the case we try to provide a temporary fix in this
%    file for them.
%    Once the package gets updated the fix will then be removed again.
%
%    For that reason, it is put into a separate bundle so that we can
%    update it easily without requiring the CTAN maintainers to
%    install a new full LaTeX system just because we take out (or add)
%    a fix for a package here.
%
%    In the best case scenario the file documented here should be
%    empty. In practice it will probably always contain one or the
%    other fix while we are waiting for the package to get updated.
%
%    \begin{quote} \textbf{Important notice:} The fixes provided here
%    are not meant to be a permanent solution, but are only provided
%    to support the transition period. They are (usually) neither
%    complete nor necessarily the best solution! Furthermore, as they
%    are done from the ``outside'', they usually add some burden and
%    slow down \LaTeX{} processing, even if the package/class is not
%    used in the document.
%
%    We will therefore remove such code as soon as possible
%    again. In practice this means that if some package never gets
%    updated/corrected, then it will eventually fail to work, because
%    after one or at most two \LaTeX{} releases we will take out the
%    transition code to ensure that this ``first aid patching''
%    doesn't get out of bounds.
%    \end{quote}
%
%  \subsection{Minor kernel fixes}
%
%    If we encounter issues with the kernel code that should get fixed
%    before the next main release we normally generate a patch release
%    for \LaTeX{}.  However, depending on the complexity of the fix we
%    might first add the fix here and generate a full patch release
%    only when a number of such issues have accumulated. This way we
%    lessen the impact on CTAN maintainers because for each tach
%    release we have to make and distribute also a matching
%    development release.
%
% \StopEventually{\setlength\IndexMin{200pt}  \PrintIndex  }
%
%
% \section{The Implementation}
%
%    This file is meant to be loaded during format generation which is
%    why we give it the extension \texttt{.ltx}.
%    \begin{macrocode}
%<*kernel>
%    \end{macrocode}
%
%    \begin{macrocode}
\def\LaTeXFirstAidDate{2020/12/14}
\def\LaTeXFirstAidVersion{v1.0i}
%    \end{macrocode}
%
%    \begin{macrocode}
\ProvidesFile{latex2e-first-aid-for-external-files.ltx}
             [\LaTeXFirstAidDate\space \LaTeXFirstAidVersion\space
               LaTeX kernel fixes to external files and packages]
%    \end{macrocode}
             %
             
%  \begin{macro}{\FirstAidNeededT}
%    This is a very simple help to ensure that we only apply first aid
%    to an unmodified package or class. It only works in the case the
%    file has already been loaded and the csname \cs{ver@\#1.\#2} got
%    defined (holding the current date, version, and short description
%    info). We then compare its content to a frozen string and make
%    the modification \verb=#3= only if both agree. If they differ we
%    assume that the package/class in question got updated by its
%    maintainer.
%    \begin{macrocode}
\ExplSyntaxOn             
\cs_new:Npn\FirstAidNeededT#1#2#3{
  \exp_args:Nc\str_if_eq:onT{ver@#1.#2}{#3}
}
\ExplSyntaxOff
%    \end{macrocode}
%  \end{macro}
%    
%    \begin{macrocode}
%</kernel>
%    \end{macrocode}
%
%
% \subsection{The \pkg{filehook} package first aid}
%     
%    The \pkg{filehook} package implements hooks into file loading
%    commands. These days this is already provided by the kernel
%    albeit not with the same user interface. Until that package gets
%    updated (to use the kernel interfaces) we provide a
%    substitution. This does not offer all hooks from \pkg{filehook}
%    but all that have been used in packages available in \TeX{} Live.
%
%    Note that this doesn't fix \pkg{currfile} because that package
%    uses \pkg{filehook} but relies on the internals of the old
%    implementation.
%
%    The package has now got an update so we aren't activating the
%    first aid. However, at the moment it basically bypasses the new
%    hook mechanism and puts the old hooks in thereby disabling, for
%    example, the possibility to re-order code through rules.
%
%    We therefore keep \texttt{filehook-ltx.sty} around as a guideline
%    for further updates.
%
%    Replacing \pkg{filehook} with a leaner version would then work
%    like this:
%    \begin{macrocode}
%<*kernel>
%\declare@file@substitution{filehook.sty}{filehook-ltx.sty}
%</kernel>
%    \end{macrocode}
%
%    What follows is a simplified (partial) implementation of the  \pkg{filehook}
%    interfaces.
%    Not implemented are:
%\begin{verbatim}
%  \AtBeginOfFiles      \AtEndOfFiles
%  \AtBeginOfInputs     \AtEndOfInputs
%  \AtBeginOfInputFile  \AtEndOfInputFile
%\end{verbatim}
%
%    \begin{macrocode}
%<*filehook>
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand\AtBeginOfEveryFile [1]
  {\AddToHook{file/before}{#1}}
\newcommand\AtEndOfEveryFile [1]
  {\AddToHook{file/after}{#1}}
%    \end{macrocode}
%    
%    \begin{macrocode}
\newcommand\AtBeginOfIncludes [1]
  {\AddToHook{include/before}{#1}}
\newcommand\AtEndOfIncludes [1]
  {\AddToHook{include/end}{#1}}
\newcommand\AfterIncludes [1]
  {\AddToHook{include/after}{#1}}
%    \end{macrocode}
%    
%    \begin{macrocode}
\newcommand\AtBeginOfPackages [1]
  {\AddToHook{package/before}{#1}}
\newcommand\AtEndOfPackages [1]
  {\AddToHook{package/after}{#1}}
%    \end{macrocode}
%    
%    \begin{macrocode}
\newcommand\AtBeginOfClasses [1]
  {\AddToHook{class/before}{#1}}
\newcommand\AtEndOfClasses [1]
  {\AddToHook{class/after}{#1}}
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand\AtBeginOfFile [2]
  {\AddToHook{file/before/#1}{#2}}
\newcommand\AtEndOfFile [2]
  {\AddToHook{file/after/#1}{#2}}
%    \end{macrocode}
%
%    Some commands offered a starred form  
%    \begin{macrocode}
\DeclareDocumentCommand \AtBeginOfPackageFile {smm}
   {\IfBooleanTF{#1}%
     {\@ifpackageloaded{#2}%
         {#3}%
         {\AddToHook{package/before/#2}{#3}}}%
     {\AddToHook{package/before/#2}{#3}}%
   }
%    \end{macrocode}
%    
%    \begin{macrocode}
\DeclareDocumentCommand \AtEndOfPackageFile {smm}
   {\IfBooleanTF{#1}%
     {\@ifpackageloaded{#2}%
         {#3}%
         {\AddToHook{package/after/#2}{#3}}}%
     {\AddToHook{package/after/#2}{#3}}%
   }
%    \end{macrocode}
%
%    Are the * forms here of any use? I know they are use 3--4 times
%    on CTAN but I wonder if those are real or mistaken usages.  
%    \begin{macrocode}
\DeclareDocumentCommand \AtBeginOfClassFile {smm}
   {\IfBooleanTF{#1}%
     {\@ifclassloaded{#2}%
         {#3}%
         {\AddToHook{class/before/#2}{#3}}}%
     {\AddToHook{class/before/#2}{#3}}%
   }
\DeclareDocumentCommand \AtEndOfClassFile {smm}
   {\IfBooleanTF{#1}%
     {\@ifclassloaded{#2}%
         {#3}%
         {\AddToHook{class/after/#2}{#3}}}%
     {\AddToHook{class/after/#2}{#3}}%
   }
%    \end{macrocode}
%    
%    \begin{macrocode}
\newcommand\AtBeginOfIncludeFile [2]
  {\AddToHook{include/before/#1}{#2}}
\newcommand\AtEndOfIncludeFile [2]
  {\AddToHook{include/end/#1}{#2}}
\newcommand\AfterIncludeFile [2]
  {\AddToHook{include/after/#1}{#2}}
%    \end{macrocode}
%
%    \begin{macrocode}
%</filehook>
%    \end{macrocode}
%
%
%
%
% \subsection{The \pkg{bidi} package first aid}
%
%     The \pkg{bidi} package adds a lot of hooks in various places and
%    those added to \cs{document} and \cs{enddocument} are now no
%    longer necessary as the kernel already provides the right hooks
%    there.
%
%    However, we aren't trying to change that but instead only make
%    sure that the existing patches still work by adding some first
%    aid after \pkg{biditools} has been loaded.
%
%    If the package gets updated one can easily take that out simply
%    through
%\begin{verbatim}
%  \RemoveFromHook{file/after/biditools.sty}[firstaid]
%\end{verbatim}
%    This makes it easy to test new bidi code while the first aid code
%    is still in the kernel.
%
%    \begin{macrocode}
%<*kernel>
%    \end{macrocode}
%
%    \begin{macrocode}
\AddToHook{file/after/biditools.sty}[firstaid]{%
  \FirstAidNeededT{biditools}{sty}%
                  {2020/05/13 v2 Programming tools for bidi package}%
  {
%    \end{macrocode}
%    \pkg{bidi} adds some code to the beginning of \cs{document} which
%    contains \cs{endgroup} and \cs{begingroup} which is no longer
%    correct.
%  
%    Patching \cs{document} using \cs{bidi@patchcmd} doesn't work so
%    we take the extra groups out by hand:
%    \begin{macrocode}
  \def\firstaid@bidi@document@patch
          \endgroup#1\begingroup#2\firstaid@bidi@document@patch
          {\unexpanded{#1#2}}%
  \edef\document{\expandafter\firstaid@bidi@document@patch\document
            \firstaid@bidi@document@patch}%
%    \end{macrocode}
%    There are also some patches into \cs{enddocument}, some continue
%    to go in but one fails, so we add that now into the right place.
%    \begin{macrocode}
  \AddToHook{enddocument/info}%
            {\let\bidi@AfterEndDocumentCheckLabelsRerun\@firstofone
              \bidi@afterenddocumentchecklabelsrerunhook}%
  }
}
%    \end{macrocode}
%    
%
%
% \subsection{The \pkg{dinbrief} class first aid}
%
%    Again a case of a no longer correct \cs{endgroup} in document.
%    Here the fix is simply though.
%    \begin{macrocode}
\AddToHook{file/after/dinbrief.cls}[firstaid]{%
  \FirstAidNeededT{dinbrief}{cls}{2000/03/02 LaTeX2e class}%
                  {\AddToHook{env/document/begin}{\begingroup}}%
}
%    \end{macrocode}
%
%
%
%
% \subsection{The \pkg{pgfpages} and \pkg{pgfmorepages} first aid}
%
%    \pkg{pgfpages} alters the \cs{shipout} primitive to support
%    multiple page up scenarios. If used together with \pkg{atbegshi}
%    that worked because the alterations done by  \pkg{atbegshi} came
%    later and so used the new definition provide by
%    \pkg{pgfpages}. Now that the code from  \pkg{atbegshi} is already
%    in the kernel this further redefinition doesn't happen with the
%    result that the change to \cs{shipout} comes to late and
%    breaks the kernel processes.
%
%    \begin{macrocode}
\ExplSyntaxOn
\AddToHook{file/after/pgfpages.sty}[firstaid]{%
%    \end{macrocode}
%    Undo overwriting \cs{shipout}:
%    \begin{macrocode}
  \cs_gset_eq:NN \shipout \pgfpages@originalshipout 
%    \end{macrocode}
%    Instead overwrite the L3 programming layer name of the
%    primitive. This is really an absolute no-go, but for now the
%    simplest solution to keep the original code running.
%
%    It will be replaced when the ``configuration points'' interface
%    for \LaTeX{} becomes available. At that point the package will be
%    able to set up a different strategy for doing shipouts and
%    without the need to overrite a primitive (which it did in the
%    past and which we do below) and then this code here can be taken
%    out again.
%    \begin{macrocode}
  \cs_set_eq:NN \pgfpages@originalshipout \tex_shipout:D
  \cs_set_eq:NN \tex_shipout:D \pgfpages@interceptshipout
}
\ExplSyntaxOff
%    \end{macrocode}
%
% Same issue with \pkg{pgfmorepages} but slightly different implementation (sigh).
%
%    \begin{macrocode}
\ExplSyntaxOn
\AddToHook{file/after/pgfmorepages.sty}[firstaid]{
  \cs_set_nopar:Npn \pgfhookintoshipout {
    \cs_set_eq:NN \pgfpages@originalshipout \tex_shipout:D
    \cs_set_eq:NN \tex_shipout:D \pgfpages@interceptshipout
  }
}
\ExplSyntaxOff
%    \end{macrocode}
%
%
% \subsection[Temporary fixes for the kernel (until the next
%             patch-level release)]
%    {Temporary fixes for the kernel \\
%     (until the next patch-level release)}
%
%
%    \begin{macrocode}
%</kernel>
%    \end{macrocode}
%
% \Finale
%
